(function(w) { if (w.fastXDM) return; var handlers = {}; var onEnvLoad = []; var env = {}; // Key generation function genKey() { var key = ''; for (var i = 0; i < 5; i++) { key += Math.ceil(Math.random() * 15).toString(16); } return key; } function waitFor(obj, prop, func, self, count) { if (obj[prop]) { func.apply(self); } else { count = count || 0; if (count < 1000) { setTimeout(function() { waitFor(obj, prop, func, self, count + 1); }, 0); } } } function attachScript(url) { setTimeout(function() { var newScript = document.createElement('script'); newScript.type = 'text/javascript'; newScript.src = url || w.fastXDM.helperUrl; waitFor(document, 'body', function() { document.getElementsByTagName('HEAD')[0].appendChild(newScript); }); }, 0); } function walkVar(value, clean) { var newValue; switch (typeof value) { case 'string': if (clean) { newValue = value.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); } else { newValue = value.replace(/'/g, '\'').replace(/"/g, '"').replace(/>/g, '>').replace(/</g, '<').replace(/&/g, '&'); } break; case 'object': if (Object.prototype.toString.apply(value) === '[object Array]') { newValue = []; for (var i = 0, len = value.length; i < len; i++) { newValue[i] = walkVar(value[i], clean); } } else { newValue = {}; for (var k in value) { if (Object.hasOwnProperty.call(value, k)) { newValue[k] = walkVar(value[k], clean); } } } break; default: newValue = value; break; } return newValue; } // Env functions function getEnv(callback, self) { if (env.loaded) { callback.apply(self, [env]); } else { onEnvLoad.push([self, callback]); } } function envLoaded() { env.loaded = true; for (var i = 0, len = onEnvLoad.length; i < len; i++) { onEnvLoad[i][1].apply(onEnvLoad[i][0], [env]); } } function applyMethod(strData, self) { getEnv(function(env) { var data = env.json.parse(strData); if (data[0]) { if (!data[1]) data[1] = []; for (var i = 0, len = data[1].length; i < len; i++) { if (data[1][i] && data[1][i]._func) { var funcNum = data[1][i]._func; data[1][i] = function() { var args = Array.prototype.slice.call(arguments); args.unshift('_func' + funcNum); self.callMethod.apply(self, args); } } else if (self.options.safe) { data[1][i] = walkVar(data[1][i], true); } } setTimeout(function() { if (!self.methods[data[0]]) { throw Error('fastXDM: Method ' + data[0] + ' is undefined'); } self.methods[data[0]].apply(self, data[1]); }, 0); } }); } function extend(obj1, obj2) { for (var i in obj2) { if (obj1[i] && typeof(obj1[i]) === 'object') { extend(obj1[i], obj2[i]) } else { obj1[i] = obj2[i]; } } } // XDM object w.fastXDM = { _id: 0, helperUrl: 'https://vk.com/js/api/xdmHelper.js', Server: function(methods, filter, options) { this.methods = methods || {}; this.filter = filter; this.options = options || {}; this.id = w.fastXDM._id++; this.key = genKey(); this.frameName = 'fXD' + this.key; this.server = true; this.methods['%init%'] = this.methods.__fxdm_i = function() { w.fastXDM.run(this.id); if (this.methods.onInit) { this.methods.onInit(); } }; handlers[this.key] = [applyMethod, this]; }, Client: function(methods, options) { this.methods = methods || {}; this.options = options || {}; this.id = w.fastXDM._id++; this.client = true; w.fastXDM.run(this.id); if (window.name.indexOf('fXD') === 0) { this.key = window.name.substr(3); } else { throw Error('Wrong window.name property.'); } this.caller = window.parent; handlers[this.key] = [applyMethod, this]; w.fastXDM.on('helper', function() { w.fastXDM.onClientStart(this); }, this); getEnv(function(env) { env.send(this, env.json.stringify(['%init%'])); var methods = this.methods; setTimeout(function() { if (methods.onInit) { methods.onInit(); } }, 0); }, this); }, onMessage: function(e) { var data = e.data; if (!data) { return false; } if (typeof data !== 'string' && !(data instanceof String)) { return false; } var key = data.substr(0, 5); if (handlers[key]) { var self = handlers[key][1]; if (self && (!self.filter || self.filter(e.origin))) { handlers[key][0](data.substr(6), self); } } }, setJSON: function(json) { env.json = json; }, getJSON: function(callback) { if (!callback) { return env.json; } getEnv(function(env) { callback(env.json); }); }, setEnv: function(exEnv) { for (var i in exEnv) { env[i] = exEnv[i]; } envLoaded(); }, _q: {}, on: function(key, act, self) { if (!this._q[key]) this._q[key] = []; if (this._q[key] == -1) { act.apply(self); } else { this._q[key].push([act, self]); } }, run: function(key) { var len = (this._q[key] || []).length; for (var i = 0; i < len; i++) { this._q[key][i][0].apply(this._q[key][i][1]); } this._q[key] = -1; }, waitFor: waitFor } w.fastXDM.Server.prototype.start = function(obj, count) { if (obj.contentWindow) { this.caller = obj.contentWindow; this.frame = obj; w.fastXDM.on('helper', function() { w.fastXDM.onServerStart(this); }, this); } else { // Opera old versions var self = this; count = count || 0; if (count < 50) { setTimeout(function() { self.start.apply(self, [obj, count + 1]); }, 100); } } } w.fastXDM.Server.prototype.destroy = function() { delete handlers[this.key]; } w.fastXDM.Server.prototype.append = function(obj, options, attrs) { var div = document.createElement('DIV'); div.innerHTML = ''; var frame = div.firstChild; var self = this; setTimeout(function() { frame.frameBorder = '0'; if (options) extend(frame, options); obj.insertBefore(frame, obj.firstChild); self.start(frame); }, 0); return frame; } w.fastXDM.Client.prototype.callMethod = w.fastXDM.Server.prototype.callMethod = function() { var args = Array.prototype.slice.call(arguments); var method = args.shift(); for (var i = 0, len = args.length; i < len; i++) { if (typeof(args[i]) === 'function') { this.funcsCount = (this.funcsCount || 0) + 1; var func = args[i]; var funcName = '_func' + this.funcsCount; this.methods[funcName] = function() { func.apply(this, arguments); delete this.methods[funcName]; } args[i] = {_func: this.funcsCount}; } else if (this.options.safe) { args[i] = walkVar(args[i], false); } } waitFor(this, 'caller', function() { w.fastXDM.on(this.id, function() { getEnv(function(env) { env.send(this, env.json.stringify([method, args])); }, this); }, this); }, this); } if (w.JSON && typeof(w.JSON) === 'object' && w.JSON.parse && w.JSON.stringify && w.JSON.stringify({a:[1,2,3]}).replace(/ /g, '') === '{"a":[1,2,3]}') { env.json = {parse: w.JSON.parse, stringify: w.JSON.stringify}; } else { w.fastXDM._needJSON = true; } // PostMessage cover if (w.postMessage) { env.protocol = 'p'; env.send = function(xdm, strData) { var win = (xdm.frame ? xdm.frame.contentWindow : xdm.caller); if (win) { try { win.postMessage(xdm.key + ':' + strData, "*"); } catch(e) { window.postMessage.call(win, xdm.key + ':' + strData, "*"); } } } if (w.addEventListener) { w.addEventListener("message", w.fastXDM.onMessage, false); } else { w.attachEvent("onmessage", w.fastXDM.onMessage); } if (w.fastXDM._needJSON) { w.fastXDM._onlyJSON = true; attachScript(); } else { envLoaded(); } } else { attachScript(); } })(window); try{stManager.done('api/xdm.js');}catch(e){}